/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package aprendizajePorRefuerzo.politica;

import aprendizajePorRefuerzo.accion.Accion;
import aprendizajePorRefuerzo.estado.Estado;
import aprendizajePorRefuerzo.funcionQ.Q;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * Fecha de creación: 08/06/2013
 * @author Oliveroing
 */
public class Softmax implements Politica {

    private Double temperatura;
    private Random random;
    private Map<Accion,Double> probabilidades;

    public Softmax(Double temperatura) {
        this.temperatura = temperatura;
        this.random = new Random(new Date().getTime());
        this.probabilidades = new HashMap<Accion, Double>();
    }

    public Double getTemperatura() {
        return temperatura;
    }

    public void setTemperatura(Double temperatura) {
        this.temperatura = temperatura;
    }

    public Random getRandom() {
        return random;
    }

    public void setRandom(Random random) {
        this.random = random;
    }

    public Map<Accion, Double> getProbabilidades() {
        return probabilidades;
    }

    public void setProbabilidades(Map<Accion, Double> probabildiades) {
        this.probabilidades = probabildiades;
    }
    
    private Map<Accion,Double> cargarProbabilidades(List<Accion> accionesPosibles, Double temperatura, Q funcionQ, Estado estado) {
        for (Accion a : accionesPosibles) {
            double numerador = Math.exp(funcionQ.getValor(estado, a)/temperatura);
            double denominador = 0;
            for (Accion i : accionesPosibles) {
                denominador = denominador + Math.exp(funcionQ.getValor(estado, i)/temperatura);
            }
            double probabilidad = numerador/denominador;
            probabilidades.put(a, probabilidad);
        }
        return probabilidades;
    }
    
    public Accion tomarAccion(Estado estado, Q funcionQ, List<Accion> accionesPosibles) {
        cargarProbabilidades(accionesPosibles, temperatura, funcionQ, estado);
        double rndm = random.nextDouble();
        double comparador = 0;
        for (Accion i : probabilidades.keySet()) {
            comparador = comparador + probabilidades.get(i);
            if (rndm <= comparador) {
                return i;
            }
        }
        return null;
    }
}
